#include <string.h>
#include "uIP_Task.h"
#include "../timer/timer.h"
#include "../lpc_config.h"
#include "../uart/uart.h"
#include "../mac/emac.h"

/* uip includes. */
#include <uip.h>
#include <uip_arp.h>
#include "httpd.h"
#include <timer.h>
#include "clock-arch.h"

static void ENET_Send(void);
static void SetMACAddress( void );


void clock_init( void );
clock_time_t clock_time( void );


void clock_init(void)
{
	T0Init(1);
	T0Start();
}

clock_time_t clock_time( void )
{
	return T0Get();
}

extern void ( EMAC_ISR_Wrapper )( void );


struct timer periodic_timer, arp_timer;

void uIP_Task_init()
{
	int i;
	uip_ipaddr_t xIPAddr;

	/* Initialise the uIP stack. */
	timer_set( &periodic_timer, 1000 / 2 );
	timer_set( &arp_timer, 1000 * 10 );
	uip_init();
	clock_init();
	uip_ipaddr( xIPAddr, uipIP_ADDR0, uipIP_ADDR1, uipIP_ADDR2, uipIP_ADDR3 );
	uip_sethostaddr( xIPAddr );
	httpd_init();


	/* Initialise the MAC. */
	while( Init_EMAC() != PASS )
    {
        delayMs( uipINIT_WAIT );
    }

	MAC_INTENABLE = INT_RX_DONE;
//    VICIntEnable |= 0x00200000;
//    VICVectAddr21 = ( int ) EMAC_ISR_Wrapper;
	SetMACAddress();

}

void uIP_Task()
{
	int i;

	/* Is there received data ready to be processed? */
	uip_len = uiGetEMACRxData( uip_buf );

	if( uip_len > 0 )
	{
		/* Standard uIP loop taken from the uIP manual. */
		if( xHeader->type == htons( UIP_ETHTYPE_IP ) )
		{
			uip_arp_ipin();
			uip_input();

			/* If the above function invocation resulted in data that
			should be sent out on the network, the global variable
			uip_len is set to a value > 0. */
			if( uip_len > 0 )
			{
				uip_arp_out();
				ENET_Send();
			}
		}
		else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) )
		{
			uip_arp_arpin();

			/* If the above function invocation resulted in data that
			should be sent out on the network, the global variable
			uip_len is set to a value > 0. */
			if( uip_len > 0 )
			{
				ENET_Send();
			}
		}
	}
	else
	{
		if( timer_expired( &periodic_timer ) )
		{
			timer_reset( &periodic_timer );
			for( i = 0; i < UIP_CONNS; i++ )
			{
				uip_periodic( i );

				/* If the above function invocation resulted in data that 
				should be sent out on the network, the global variable 
				uip_len is set to a value > 0. */
				if( uip_len > 0 )
				{
					uip_arp_out();
					ENET_Send();
				}
			}

			/* Call the ARP timer function every 10 seconds. */
			if( timer_expired( &arp_timer ) )
			{
				timer_reset( &arp_timer );
				uip_arp_timer();
			}
		}
		else
		{
			/* We did not receive a packet, and there was no periodic
			processing to perform.  Block for a fixed period.  If a packet
			is received during this period we will be woken by the ISR
			giving us the Semaphore. */
			//xSemaphoreTake( xEMACSemaphore, configTICK_RATE_HZ / 2 );
			return;
		}
	}
}

static void ENET_Send(void)
{
    RequestSend();

    /* Copy the header into the Tx buffer. */
    CopyToFrame_EMAC( uip_buf, uipTOTAL_FRAME_HEADER_SIZE );
    if( uip_len > uipTOTAL_FRAME_HEADER_SIZE )
    {
        CopyToFrame_EMAC( uip_appdata, ( uip_len - uipTOTAL_FRAME_HEADER_SIZE ) );
    }

    DoSend_EMAC( uip_len );
}
/*-----------------------------------------------------------*/

static void SetMACAddress( void )
{
struct uip_eth_addr xAddr;

	/* Configure the MAC address in the uIP stack. */
	xAddr.addr[ 0 ] = uipMAC_ADDR0;
	xAddr.addr[ 1 ] = uipMAC_ADDR1;
	xAddr.addr[ 2 ] = uipMAC_ADDR2;
	xAddr.addr[ 3 ] = uipMAC_ADDR3;
	xAddr.addr[ 4 ] = uipMAC_ADDR4;
	xAddr.addr[ 5 ] = uipMAC_ADDR5;
	uip_setethaddr( xAddr );
}

#define SetLED(___x___ , ___y___) uart_puts("\nLed: "); uart_putc(___x___+'0'); uart_putc(___y___+'0')
#define LCD_puts(__z__) uart_puts("\nLcd: "); uart_puts(__z__);

void ApplicationProcessFormInput( char *pcInputString, int xInputLength )
{
char *c, *pcText;

	/* Process the form input sent by the IO page of the served HTML. */

	c = strstr( pcInputString, "?" );
    if( c )
    {
		/* Turn LED's on or off in accordance with the check box status. */
		if( strstr( c, "LED0=1" ) != NULL )
		{
			SetLED( 5, 0 );
		}
		else
		{
			SetLED( 5, 1 );
		}		
		
		if( strstr( c, "LED1=1" ) != NULL )
		{
			SetLED( 6, 0 );
		}
		else
		{
			SetLED( 6, 1 );
		}		

		if( strstr( c, "LED2=1" ) != NULL )
		{
			SetLED( 7, 0 );
		}
		else
		{
			SetLED( 7, 1 );
		}

		/* Find the start of the text to be displayed on the LCD. */
        pcText = strstr( c, "LCD=" );
        pcText += strlen( "LCD=" );

        /* Terminate the file name for further processing within uIP. */
        *c = 0x00;

        /* Terminate the LCD string. */
        c = strstr( pcText, " " );
        if( c != NULL )
        {
            *c = 0x00;
        }

        /* Add required spaces. */
        while( ( c = strstr( pcText, "+" ) ) != NULL )
        {
            *c = ' ';
        }
        LCD_puts(pcText);
    }
}

